package po.utils;

import po.entity.ParamValue;
import po.enums.Operator;
import po.exception.ParamValueInCompatibleException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by guowei on 2019/6/9.
 */
public class ParamValueHandler {
    // checkParamValueCompatible return the compact result of the pv1 and pv2
    public static ParamValue checkParamValueCompatible(ParamValue pv1, ParamValue pv2, Operator operator) throws Exception {
        if (pv1.getType() != pv2.getType()) {
            throw new ParamValueInCompatibleException(pv1, pv2);
        }
        ParamValue pvResult = new ParamValue(pv1.getType(), pv1.getValueEnum(), pv1.getMax(), pv1.getMin());
        switch (operator) {
            // operator value can be two kinds, for each kind, should do following calculation
            // the result will be set to the pv1
            // this will influence the outer method param passing order
            case AND:
                switch (pv1.getType()) {
                    case SCOPE:
                        double newMin = Math.max(pv1.getMin(), pv2.getMin());
                        double newMax = Math.min(pv1.getMax(), pv2.getMax());
                        if(newMin > newMax) {
                            throw new ParamValueInCompatibleException(pv1, pv2);
                        }
                        // assign new scope to result
                        pvResult.setMax(newMax);
                        pvResult.setMin(newMin);
                        break;
                    case ENUM:
                        Map<String, Integer> tmpResult = new HashMap<>();
                        List<String> newValueEnum = new ArrayList<>();
                        for (String v1 : pv1.getValueEnum()) {
                            // default, we consider the valueEnum list contains no same value
                            tmpResult.put(v1, 1);
                        }
                        for (String v2 : pv2.getValueEnum()) {
                            if(tmpResult.containsKey(v2)) {
                                newValueEnum.add(v2);
                            }
                        }
                        pvResult.setValueEnum(newValueEnum);
                        break;
                }
                break;
            case OR:
                switch (pv1.getType()) {
                    case SCOPE:
                        double newMin = Math.min(pv1.getMin(), pv2.getMin());
                        double newMax = Math.max(pv1.getMax(), pv2.getMax());
                        // this check branch should never enter
                        if(newMin > newMax) {
                            throw new ParamValueInCompatibleException(pv1, pv2);
                        }
                        // assign new scope to pv1
                        pvResult.setMax(newMax);
                        pvResult.setMin(newMin);
                        break;
                    case ENUM:
                        Map<String, Integer> tmpResult = new HashMap<>();
                        List<String> newValueEnum = new ArrayList<>();
                        for (String v1 : pv1.getValueEnum()) {
                            // default, we consider the valueEnum list contains no same value
                            tmpResult.put(v1, 1);
                            newValueEnum.add(v1);
                        }
                        for (String v2 : pv2.getValueEnum()) {
                            if(!tmpResult.containsKey(v2)) {
                                newValueEnum.add(v2);
                            }
                        }
                        pvResult.setValueEnum(newValueEnum);
                        break;
                }
                break;
        }
        return pvResult;
    }
}
